package com.junjie.springcloud.service;

import cn.hutool.core.util.IdUtil;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.stereotype.Service;

// 全局兜底方法的配置 (如果在@HystrixCommand 注解中没有 fallbackMethod 指定固定的错误
// 兜底方法就用这个 payment_Global_FallBackMethod 方法)
@DefaultProperties(defaultFallback = "payment_Global_FallBackMethod")
@Service
public class PaymentService {

    //正常访问
    public String paymentInfo_Ok(Integer id) {
        return "线程池：" + Thread.currentThread().getName() + "paymentInfo Ok:" + id + "你成功了!";
    }

    //模拟出错
    @HystrixCommand(/*fallbackMethod = "paymentInfo_TimeoutHandler",*/ commandProperties = {
            //设置峰值，超过 3 秒，就会调用兜底方法，这个时间也可以由feign控制
            //3 秒以内是正常的业务逻辑，超过这个时间就会出错
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds", value = "3000")
    })
    public String paymentInfo_Timeout(Integer id) {
        //int i = 10/0; //这个也会报错（也会调用下面那个兜底的方法）
        try {
            Thread.sleep(4000);
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池：" + Thread.currentThread().getName() + "paymentInfo Timeout:" + id + "你出错了!";
    }

    //这就是兜底的解决方法（上面那个方法出错以后就会调用这个方法）
    //当前的服务不可用了，就做服务降级，兜底方案都是 paymentInfo_TimeoutHandler
    public String paymentInfo_TimeoutHandler(Integer id) {
        return "线程池：" + Thread.currentThread().getName() + "paymentInfo Timeout:" + id + "对不起我是服务降级的方法!";
    }

    //全局的兜底处理方法
    public String payment_Global_FallBackMethod() {
        return "Global 异常处理信息，请稍后再试，";
    }

    // --------------------------------------------------------------
    // 服务熔断 demo
    //=====服务熔断
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback", commandProperties = {
            @HystrixProperty(name="circuitBreaker.enabled", value="true"),  // 是否开启断路器
            @HystrixProperty(name="circuitBreaker.requestVolumeThreshold", value="10"),  //请求次数
            @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds", value="10000"), // 时间窗口期
            @HystrixProperty(name="circuitBreaker.errorThresholdPercentage", value="60"),  // 失败率达到多少后跳闸
            //整体意思：10秒内 10次请求，有6次失败，就跳闸 (这里跳闸之后就会直接调用降级的方法)
    })
    //@HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback")
    public String paymentCircuitBreaker(Integer id){
        if(id < 0){
            throw new RuntimeException("*****id，不能为负数");
        }
        String serialNumber = IdUtil.simpleUUID();
        return Thread.currentThread().getName() + "\t" + "调用成功，流水号：" + serialNumber;
    }

    public String paymentCircuitBreaker_fallback(Integer id){
        return "id 不能为负数，请稍后再试....";
    }
}
